00:03
MALE: In this video,
I'll show you
00:06
how to write a
test function,
00:08
which will automatically
00:10
verify the correctness
00:11
of a different function
00:13
that was previously
written.
00:17
This is the video
that goes with
00:19
lesson seven
and here is
00:21
the prepare content
for that lesson.
00:24
During this video, I will
00:26
use the "pytest" module,
00:28
which is a third
party module.
00:30
This means that it
was not installed
00:32
when I installed
Python on my computer.
00:35
Instead, I will
have to install
00:38
"pytest" on my computer
00:39
just as you will
have to do.
00:41
After I get "pytest" installed,
00:44
then I will use the
assert command,
00:46
which is part of Python,
something like that.
00:50
And I will also use
the approx function,
00:53
which is part of
the "pytest" module.
00:57
And finally,
just as shown is...
01:00
the prepare content,
01:02
I will use "pytest"
dot main like this.
01:05
So I'll use all
those parts.
01:07
Let's first make sure
01:09
that "pytest" is installed
on my computer.
01:13
Looking in the checkpoint
for this lesson,
01:16
I see there are
two commands.
01:18
The first one
doesn't actually
01:21
the second one
does. Instead the
01:22
first one updates module,
01:25
a standard module
called pip.
01:28
Pip is what we use to
install other modules.
01:31
But we first have to
make sure that we have
01:33
the latest version on
01:34
our computer before
we can use Pip.
01:36
So to do that, I'll copy
01:37
this and I've selected it,
01:39
and then I press Control
01:41
C. Go over here to VS Code
01:44
and open a new
terminal frame
01:46
and paste that command
into the terminal.
01:49
I used Control-V to do
that and then I press
01:51
Enter. On my computer,
01:55
I can see that
I already had
01:57
the latest version of
01:58
Pip and also setup tools.
02:01
And I can see that
because this,
02:04
say here that
those requirements
02:06
are already satisfied.
On your computer
02:08
you may not have had
02:09
the latest versions
and so you
02:11
would have seen
messages that
02:12
say they were
being updated.
02:14
If you didn't
see either of
02:16
those things when you
02:17
pressed Enter for
this command,
02:19
that the requirements
were already
02:21
satisfied or messages
02:22
saying they were
being installed,
02:23
then the command
did not work.
02:26
That happens sometimes on
02:30
running the Mac
OS and Windows.
02:32
If you're on a computer
running the Mac OS,
02:34
you can still use exactly the
same command here,
02:37
except you need to
replace this word python
02:41
with the word python3 and
02:43
try executing and
see if that works.
02:46
If you're on a computer
running...running
02:48
Windows and this command,
02:49
this command here
did not work,
02:51
then you can still
use the same command
02:53
except you could
try instead of
02:56
the word python
here, just use
02:58
the letters py. P-Y, py.
03:01
Use that in
place of python.
03:03
If neither of those works
03:05
for you on your computer,
03:06
then you need
to contact your
03:07
teacher or a teaching assistant
03:08
or a fellow student or
post in Slack, get some help
03:11
so you can get pip updated.
03:13
After you have
pip updated,
03:15
then you'll need to
install "pytest".
03:17
So that's the second
command here.
03:19
I'll execute it
in the same way
03:21
I've selected it and I
03:22
pressed Control C to
03:24
copy it to the clipboard.
03:25
And then I click
over here in the,
03:29
in the terminal
frame and I
03:31
paste it with Control
V and press enter.
03:34
And it looks
like I already
03:36
had "pytest" installed.
03:38
I can see that because it
03:39
says requirement
already satisfied.
03:41
But you probably
saw a message
03:43
saying that it was
installing "pytest".
03:44
Again, if neither of
03:46
those things happened for
03:47
you on your computer,
03:48
then you'll need to
try either python3,
03:51
the word python3 in
place of this python,
03:53
or just the word py,
03:55
P-Y in place of
that word python.
03:58
Once it's installed, then
04:00
we can close the terminal
04:02
and get started writing
our test functions.
04:06
So I'm going to write two
04:08
test functions today.
04:09
I'll write one for this function
named wind chill
04:12
and a second one
for this function
04:15
I'll start by
making a new file.
04:18
You could press File here,
04:20
click file on
the file menu
04:23
Or do like I'm going to do and
just press Control-N.
04:28
this file immediately
with the dot p-y
04:31
file extensions
so that I get
04:32
color syntax highlighting
04:34
right from the beginning.
04:35
And I'll save it as
test weather dot py.
04:39
I chose that name because
04:42
the file that contains
the functions
04:44
which I'm supposed
to be testing,
04:46
that file's name is
weather dot py.
04:48
So I chose this test
weather dot py,
04:53
to indicate that
I'm writing
04:55
test functions
for the functions
04:57
in this weather file.
04:59
The first thing
I need to do,
05:01
just as is shown in
the prepare content,
05:06
some stuff so that I
05:08
can actually
import some things
05:09
so that I actually
write the test.
05:11
So I'll just copy those.
05:13
Those imports
or similar ones
05:15
are also shown in
the checkpoint.
05:17
There they are in the
checkpoint and they're
05:18
also shown in the
team activities,
05:20
similar ones, there they
are in the team activity.
05:22
I'll use the ones
from the prepare content.
05:26
Okay, this is convenient.
05:28
I am importing
something from
05:31
the file named weather
05:32
dot py, that's this one.
05:33
However, I'm not
importing or testing
05:36
this function
cells from fahr,
05:37
I don't want to do that.
05:40
import the test
wind chill,
05:46
import and test
heat index,
05:48
so I'll copy that and
paste that in there.
05:51
This line I need
because I intend to
05:55
test functions which will
05:56
return floating
point numbers.
05:58
I can see that clearly
06:00
looking at the
wind chill function,
06:02
I can see clearly that
06:04
the results of
the calculation
06:05
here are floating
point numbers
06:07
because of all of
these floating
06:08
point numbers
in the formula.
06:10
I can also see that the
06:11
round function
is used and it
06:13
rounds the result to
06:14
one place after
the decimal point.
06:16
So that will be a
floating point number.
06:20
tests that use floating
point numbers,
06:22
we need to use the
approx function.
06:25
I'll also need the "pytest"
module itself,
06:28
so it's just imported
06:29
all by itself, great.
06:30
Let's write the
first test function.
06:32
I'll start with
its header,
06:34
start with the
keyword def.
06:36
And then the naming
convention says,
06:38
I should start this
test function with
06:41
the word test and
then an underscore,
06:43
and then the name of
06:44
whatever function it is
I'm planning to test.
06:46
I'm currently testing wind chill,
06:49
so that's what comes after
06:51
test underscore with
no parameters
06:53
in the parameter list.
06:56
Great, to test a function,
06:59
what I need is I need
either to do this with
07:02
a calculator or
I need someone
07:04
to give me some
test results.
07:06
And here I have some.
07:08
This little table shows
that if we pass in 0
07:12
for the temperature
in the Fahrenheit
07:14
and three for
the wind speed,
07:16
that the windshield
function
07:17
should return
negative 6.9.
07:19
Let's put that in
the function header.
07:23
the temperature and three
for the wind speed,
07:26
then this function should
07:27
return negative 6.9.
07:30
So in the test
wind chill function,
07:33
I will write code to
07:34
verify that that
actually happens.
07:37
First, I'll write code to
07:38
call the wind chill
function.
07:40
That could look like this.
07:42
Chill, there's my variable,
wind chill
07:46
I'll pass in 0 for
the temperature in
07:48
Fahrenheit and three
for the wind speed.
07:52
And that will then be
07:54
that will call the
wind chill function,
07:55
which will do its
calculations and then
07:57
store a result in
the chill variable.
08:00
Then I'll write an
assert statement
08:02
to verify, that chill is actually
08:05
equal to the negative 6.9.
08:10
negative 6.9 is a
floating point number
08:12
so I need to use the
box function in here.
08:15
And this is
exactly as it's
08:17
shown in the
prepare content.
08:20
There it is similar
shown right there.
08:27
would call the
first test case,
08:29
or in other words,
the first set of
08:31
values in our
table right there.
08:33
I need to do that
two more times.
08:36
So I'll just put
a blank line
08:37
there for readability.
08:39
That's just for
the human and
08:40
the computer doesn't care.
08:41
Then I'll copy those.
08:43
In fact, I have to do
it two more times,
08:45
so I might as well
while I'm at it,
08:46
paste it two more times.
08:49
numbers here it
looks like is
08:51
negative 5 for
the temperature
08:52
and 5 for the wind speed.
08:54
So I'll replace those,
08:56
negative 5 and 5 for
the wind speed.
08:59
And then that's
supposed to return
09:03
I'll put that in here.
09:04
And finally, the last set
09:05
of values over here,
09:06
negative 10, 3 should
return negative 18.2.
09:10
Let's put that in there.
09:11
Negative 10
Fahrenheit with
09:13
a wind speed of 3
miles per hour,
09:15
should give back negative 18.2
degrees Fahrenheit.
09:20
We can save this file
and we're ready to run.
09:23
Oh, we're not quite ready.
09:25
You might remember
in the past that
09:27
we put main down here
09:29
a call to main in
order to start
09:31
our, our program
executing.
09:34
We don't have a
main function
09:36
here when we write
test functions.
09:38
Instead, main is inside
09:40
of the "pytest" module.
09:42
That's why we will use
09:44
this code that will
call "pytest" dot main.
09:49
And that same
code is shown
09:50
in the prepare content.
09:51
It's shown in
the checkpoint,
09:54
there it is shown in the
checkpoint, and it's also
09:56
shown in the team activity.
09:57
That's what we do to start
09:59
test functions executing
is we call main,
10:02
which is inside of
the "pytest" module.
10:05
The people who
wrote "pytest"
10:07
wrote that main for us.
10:10
So we have the
call to main,
10:11
we have a few arguments
here. Actually,
10:15
one argument that's a list
10:17
is the correct
way to say that.
10:19
This is important, that we
10:20
get this file name right.
10:22
It turns out that we're
10:23
lucky we have it right.
10:24
Notice I'm writing code
10:26
in a file name test
weather dot py,
10:28
and that's what
this is right here,
10:29
test weather dot py.
10:31
Okay, now I'm
ready to run
10:33
and test the wind
chill function.
10:36
and I press the
Run button here,
10:38
the green triangle.
And it runs.
10:43
And it tells me, that's
10:44
awesome that the
test passed.
10:46
So what does that
mean that it passed?
10:48
It means that the
computer read this file,
10:53
it read test
weather dot py,
10:54
it saw that this
was a call to
10:58
inside of "pytest" dot main,
11:00
which we didn't write,
11:01
it's a function
that's inside
11:02
of the "pytest" module.
11:04
It called, that
"pytest" dot main,
11:07
it found all of the
functions in this file,
11:10
which start with
the word test
11:12
and underscore,
start with that.
11:14
Found all of those and then
11:15
executed it, there
is only one.
11:17
So it executed this.
11:19
As part of the execution,
11:21
the comp...uh
the computer called
11:23
the wind chill function, got
11:25
the value and then
made sure that
11:27
that value was
approximately negative 6.9.
11:29
And then it did
it again, called
11:31
the wind chill function
a second time and made
11:33
sure that the result of
11:34
that second call
was approximately
11:36
negative 16.4 and so
on to the third time.
11:40
I'm going to introduce
a failure on purpose.
11:44
I'm going to
introduce a failure
11:46
so that we can see what
a fail looks like.
11:48
So I'll go back to
the program function,
11:51
which is here in
weather dot py,
11:52
the one we're
trying to test.
11:54
And I will
purposely change
11:56
this number
instead of 35.74.
11:59
I will purposely
change it to 36.
12:03
but I'm introducing
it on purpose so that
12:05
we can see what a test
failure looks like.
12:07
I saved the file after I
12:10
made this change,
this mistake,
12:11
I just saved
it by pressing
12:13
Control S. And then I'll
12:16
the test file and I
will run it again.
12:18
I think I'll get a clean
12:20
terminal, so close that one,
and then run it again.
12:22
And it tells me that
the test failed.
12:25
And not only does it
tell me that it failed,
12:27
it tells me what happened.
12:29
It said it tried to
assert that negative
12:32
6.6 was equal to
negative 6.9,
12:35
but those two
just aren't the
12:36
same, so the test failed.
12:38
So that happened on
this line right here.
12:42
The computer called the
wind chill function,
12:44
and it returned, the
wind chill function
12:47
returned negative 6.6,
which is wrong.
12:50
And then the
computer checked to
12:52
see if negative 6.6 was
12:53
approximately
equal to negative
12:55
6.9 and that failed,
so the whole test failed.
12:58
If I go and replace that,
13:01
that mistake that I
purposely introduced,
13:03
I replace it with
what it should
13:05
be and then save
the file again,
13:07
that's important, that
I save the file again.
13:09
Control S is what I did.
13:11
Then come back here and run
13:13
the test will
again pass. Great.
13:17
Let's now go on and write
13:18
a second test function.
13:20
That would be the
function that will
13:22
test the heat
index function.
13:25
Wow, this is a fairly
complex formula.
13:28
It's pretty long. It's got
13:30
a lot of floating
point numbers in it.
13:31
Again, I notice
the rounding
13:33
to one place after
the decimal,
13:35
so I can clearly see when
13:36
this heat index
function is done,
13:38
it will return a
floating point number.
13:41
We have in the assignment
13:43
here we have
another table of
13:45
values that are
known to be correct.
13:47
So we'll use those values
13:49
to call the heat
index function.
13:52
All right, it's
a new function,
13:55
so here we go, test,
13:57
notice the naming
convention again,
13:58
it starts with
test and then
14:00
underscore. Test
heat index,
14:03
no parameters to
test functions
14:05
usually, not always,
but usually.
14:08
Okay, I'm going to
write this function
14:11
slightly differently
from the previous one.
14:14
It's not a lot different.
14:15
What I'll do is
make a shortcut.
14:17
I will take these
two lines of
14:19
code and just combine
them into one.
14:22
So instead of writing
them as two lines,
14:24
I'll write them on one line,
14:25
so that will look like this.
14:26
Assert and then I will
call the heat
14:29
index function,
heat index,
14:33
How many parameters
does heat index have?
14:35
Oh it has two. It has
a temperature
14:38
in Fahrenheit and a
relative humidity.
14:40
Those are the
two parameters.
14:42
this table
actually gives me
14:45
some values for
those parameters.
14:48
So here in the heat index,
14:50
I need two arguments,
there they are,
14:53
Fahrenheit and 80
percent humidity.
14:56
And that should...we want to
14:58
verify that that returns
15:00
approximately 84.2
degrees Fahrenheit.
15:04
That's where I
want to verify.
15:05
Now, I could retype that
line of code again,
15:08
but I really
don't want to,
15:10
when I don't need to, I'll
15:11
just copy and paste it
15:12
because I have two
more sets of values.
15:15
So copy and paste
is an important
15:17
speedup, an
important shortcut
15:21
if you're careful
with it. Let's see.
15:23
So instead of
using 80 degrees,
15:25
I want to use 85 degrees.
15:27
It still is 80 percent
relative humidity,
15:29
that's coming from
the table here.
15:31
And according
to this table,
15:33
that should give us back
15:34
a value of 96.8.
Great, I've done that.
15:39
Finally, I'll do the
last set of values,
15:42
96 and 70% relative humidity.
15:45
Again, I just got this
from the table over here.
15:48
And according
to that table,
15:49
that should give us
back a whopping
15:52
126.4 degrees
Fahrenheit.
15:57
The heat index is
supposed to be
16:00
a measure of how
humans feel heat.
16:04
weather that is 96
degrees Fahrenheit,
16:07
which is pretty
pretty hot.
16:08
That's like Texas
weather. It's Rexburg, Idaho
16:12
weather maybe one
day out of the year,
16:15
but it's Texas, or lots of
16:16
Phoenix, part of
Los Angeles
16:18
weather, if you're
in that weather and
16:20
the relative humidity
is 70 percent
16:22
and you're outdoors,
16:24
your body will feel like
the temperature's
16:26
126.4, it will
sweat so much.
16:29
So you have to be
really careful to
16:31
stay in the shade
and drink lots of water.
16:33
Okay. That was an aside.
16:34
Let's run the tests again.
16:36
We don't have to
change anything
16:38
else down here
on this line.
16:40
Because this
line right here
16:42
tells "pytest" to
look in the test
16:45
weather dot py file
and find all of
16:47
the functions that start
16:49
with test underscore.
16:50
There's one, there's two,
16:52
and execute all of them.
16:54
So just that line of code
16:55
will execute all
of our tests.
16:57
Let's save the file
and run the test,
17:00
see if they pass. Great.
17:03
Both of them passed.
That's awesome.
17:06
That's what we
like to see.
17:07
Once again, I'm going
to introduce a mistake,
17:10
but this time I'm going
17:11
to purposefully introduce
17:13
the mistake in
the test function
17:15
and not in the
program function.
17:18
So here instead of
this saying 96.8,
17:23
something obviously wrong,
17:25
72. Change it to that.
17:27
And I'll run the
tests again.
17:30
This time what I
see, the first test
17:33
passed, test
wind chill passed.
17:35
I didn't make any
changes there,
17:37
so it should have
passed. But test
17:39
heat index failed
and again
17:40
it tells me what happened.
17:42
It attempted, "pytest"
attempted to verify that
17:46
96.8 was really
equal to 72.
17:49
And that's just
clearly not the case.
17:52
And so the test failed.
17:53
And that's this
line right here.
17:55
I can see that
because of the 72.
17:57
So I'll put back
the right code before
18:00
I introduce the mistake.
18:02
The reason I
introduced the mistake
18:05
first in the
program function
18:07
over here in wind chill.
18:09
And then second, I
introduced on purpose,
18:11
a mistake in the test
function, was to help
18:14
you see that when
the tests fail,
18:19
certain which function
has the mistake.
18:23
We don't know if it's
the program function
18:25
that we're trying
to verify is
18:28
the test function that is
18:30
supposed to be
doing the verification.
18:32
Once we see a
test failure,
18:34
we have to use our brains.
18:36
We have to, have to try to
18:37
figure out and
play detective,
18:39
figure out what is wrong
to fix the mistakes.
18:43
This concludes
the video that
18:46
shows you how to write two
18:47
test functions
that automatically
18:50
verify that two previously
written functions
18:53
are returning,
calculating, and
18:55
returning the
correct values.
18:58
Keep in mind, you can
18:59
write test functions for
19:02
functions that
calculate integers
19:04
or that returns strings,
19:08
pictures if you wanted to,
19:09
that would be harder,
but it can be done.
19:11
We can write a
test function for
19:14
any function that returns
any sort of value.
19:17
The function can return
19:19
a list or a dictionary,
19:20
and we can still write
19:21
a test function to
verify it correctly.